<template>
  <div class="workflow-designer">
    <!-- 顶部工具栏 -->
    <div class="toolbar">
      <div class="toolbar-left">
        <el-button type="primary" @click="handleSave" :icon="DocumentAdd">
          保存流程
        </el-button>
        <el-button @click="handleValidate" :icon="CircleCheck">
          验证流程
        </el-button>
        <el-button @click="handleClear" :icon="Delete">
          清空画布
        </el-button>
        <el-button @click="handleZoomIn" :icon="ZoomIn">
          放大
        </el-button>
        <el-button @click="handleZoomOut" :icon="ZoomOut">
          缩小
        </el-button>
        <el-button @click="handleFitView" :icon="FullScreen">
          适应画布
        </el-button>
      </div>
      <div class="toolbar-right">
        <span class="workflow-name">{{ workflowConfig.name || '未命名流程' }}</span>
        <el-button @click="handleWorkflowConfig" :icon="Setting">
          流程配置
        </el-button>
      </div>
    </div>

    <div class="designer-container">
      <!-- 左侧节点面板 -->
      <div class="node-panel">
        <div class="panel-header">
          <h3>流程节点</h3>
        </div>
        <div class="node-list">
          <div class="node-group" v-for="group in nodeGroups" :key="group.name">
            <div class="group-title">{{ group.name }}</div>
            <div class="group-items">
              <div 
                v-for="node in group.nodes" 
                :key="node.type"
                class="node-item"
                draggable="true"
                @dragstart="handleNodeDragStart(node)"
              >
                <div class="node-icon" :class="node.color">
                  <el-icon><component :is="node.icon" /></el-icon>
                </div>
                <span>{{ node.label }}</span>
              </div>
            </div>
          </div>
        </div>
      </div>

      <!-- 中间画布区域 -->
      <div class="canvas-panel">
        <div class="panel-header">
          <h3>流程设计</h3>
          <div class="canvas-actions">
            <span class="zoom-info">{{ Math.round(zoomLevel * 100) }}%</span>
          </div>
        </div>
        <div 
          class="canvas-container"
          ref="canvasContainer"
          @drop="handleCanvasDrop"
          @dragover="handleCanvasDragOver"
          @click="handleCanvasClick"
        >
          <div 
            class="canvas"
            :style="{
              transform: `scale(${zoomLevel}) translate(${panX}px, ${panY}px)`
            }"
          >
            <!-- 网格背景 -->
            <div class="grid-background"></div>
            
            <!-- 连接线 -->
            <svg class="connections" width="100%" height="100%">
              <defs>
                <marker id="arrowhead" markerWidth="10" markerHeight="7" 
                        refX="9" refY="3.5" orient="auto">
                  <polygon points="0 0, 10 3.5, 0 7" fill="#606266" />
                </marker>
              </defs>
              <path 
                v-for="connection in connections" 
                :key="connection.id"
                :d="getConnectionPath(connection)"
                stroke="#606266"
                stroke-width="2"
                fill="none"
                marker-end="url(#arrowhead)"
                class="connection-line"
                @click="selectConnection(connection)"
              />
            </svg>

            <!-- 流程节点 -->
            <div 
              v-for="node in workflowNodes" 
              :key="node.id"
              class="workflow-node"
              :class="{
                active: selectedNode?.id === node.id,
                [node.type]: true
              }"
              :style="{
                left: node.x + 'px',
                top: node.y + 'px'
              }"
              @click.stop="selectNode(node)"
              @mousedown="startDrag(node, $event)"
            >
              <div class="node-header">
                <div class="node-icon" :class="getNodeConfig(node.type).color">
                  <el-icon><component :is="getNodeConfig(node.type).icon" /></el-icon>
                </div>
                <span class="node-title">{{ node.title || getNodeConfig(node.type).label }}</span>
                <el-button 
                  size="small" 
                  type="danger" 
                  @click.stop="removeNode(node)"
                  class="node-delete"
                >
                  <el-icon><Close /></el-icon>
                </el-button>
              </div>
              <div class="node-content">
                <div class="node-description">{{ node.description || '点击配置节点' }}</div>
              </div>
              
              <!-- 连接点 -->
              <div 
                class="connection-point input"
                v-if="node.type !== 'start'"
                @click.stop="handleConnectionPoint(node, 'input')"
              ></div>
              <div 
                class="connection-point output"
                v-if="node.type !== 'end'"
                @click.stop="handleConnectionPoint(node, 'output')"
              ></div>
            </div>

            <!-- 临时连接线 -->
            <svg v-if="tempConnection" class="temp-connection" width="100%" height="100%">
              <path 
                :d="getTempConnectionPath()"
                stroke="#409eff"
                stroke-width="2"
                stroke-dasharray="5,5"
                fill="none"
              />
            </svg>
          </div>
        </div>
      </div>

      <!-- 右侧属性配置 -->
      <div class="property-panel">
        <div class="panel-header">
          <h3>节点配置</h3>
        </div>
        <div class="property-content">
          <div v-if="!selectedNode" class="no-selection">
            <p>请选择一个节点进行配置</p>
          </div>
          <div v-else class="node-config">
            <el-form :model="selectedNode" label-width="80px" size="small">
              <!-- 基础配置 -->
              <div class="config-group">
                <div class="group-title">基础配置</div>
                <el-form-item label="节点名称">
                  <el-input v-model="selectedNode.title" placeholder="请输入节点名称" />
                </el-form-item>
                <el-form-item label="节点描述">
                  <el-input 
                    v-model="selectedNode.description" 
                    type="textarea" 
                    placeholder="请输入节点描述" 
                  />
                </el-form-item>
              </div>

              <!-- 审批节点配置 -->
              <div class="config-group" v-if="selectedNode.type === 'approval'">
                <div class="group-title">审批配置</div>
                <el-form-item label="审批人">
                  <el-select v-model="selectedNode.config.approver" placeholder="请选择审批人">
                    <el-option label="直接主管" value="direct_manager" />
                    <el-option label="部门经理" value="department_manager" />
                    <el-option label="指定人员" value="specific_user" />
                  </el-select>
                </el-form-item>
                <el-form-item label="审批方式">
                  <el-radio-group v-model="selectedNode.config.approvalType">
                    <el-radio label="single">单人审批</el-radio>
                    <el-radio label="multiple">多人审批</el-radio>
                  </el-radio-group>
                </el-form-item>
                <el-form-item label="超时处理" v-if="selectedNode.config.approvalType === 'single'">
                  <el-input-number v-model="selectedNode.config.timeout" :min="1" /> 小时
                </el-form-item>
              </div>

              <!-- 条件节点配置 -->
              <div class="config-group" v-if="selectedNode.type === 'condition'">
                <div class="group-title">条件配置</div>
                <div class="condition-list">
                  <div v-for="(condition, index) in selectedNode.config.conditions" :key="index" class="condition-item">
                    <el-form-item label="字段">
                      <el-input v-model="condition.field" placeholder="请输入字段名" />
                    </el-form-item>
                    <el-form-item label="操作符">
                      <el-select v-model="condition.operator">
                        <el-option label="等于" value="eq" />
                        <el-option label="不等于" value="ne" />
                        <el-option label="大于" value="gt" />
                        <el-option label="小于" value="lt" />
                        <el-option label="包含" value="contains" />
                      </el-select>
                    </el-form-item>
                    <el-form-item label="值">
                      <el-input v-model="condition.value" placeholder="请输入值" />
                    </el-form-item>
                    <el-button size="small" type="danger" @click="removeCondition(index)">
                      删除
                    </el-button>
                  </div>
                  <el-button size="small" @click="addCondition">添加条件</el-button>
                </div>
              </div>

              <!-- 脚本节点配置 -->
              <div class="config-group" v-if="selectedNode.type === 'script'">
                <div class="group-title">脚本配置</div>
                <el-form-item label="脚本类型">
                  <el-select v-model="selectedNode.config.scriptType">
                    <el-option label="JavaScript" value="javascript" />
                    <el-option label="Python" value="python" />
                    <el-option label="SQL" value="sql" />
                  </el-select>
                </el-form-item>
                <el-form-item label="脚本内容">
                  <el-input 
                    v-model="selectedNode.config.script" 
                    type="textarea" 
                    :rows="8"
                    placeholder="请输入脚本内容" 
                  />
                </el-form-item>
              </div>

              <!-- 通知节点配置 -->
              <div class="config-group" v-if="selectedNode.type === 'notification'">
                <div class="group-title">通知配置</div>
                <el-form-item label="通知方式">
                  <el-checkbox-group v-model="selectedNode.config.notifyMethods">
                    <el-checkbox label="email">邮件</el-checkbox>
                    <el-checkbox label="sms">短信</el-checkbox>
                    <el-checkbox label="system">系统通知</el-checkbox>
                  </el-checkbox-group>
                </el-form-item>
                <el-form-item label="通知对象">
                  <el-input v-model="selectedNode.config.recipients" placeholder="请输入通知对象" />
                </el-form-item>
                <el-form-item label="通知模板">
                  <el-input 
                    v-model="selectedNode.config.template" 
                    type="textarea" 
                    placeholder="请输入通知模板" 
                  />
                </el-form-item>
              </div>
            </el-form>
          </div>
        </div>
      </div>
    </div>

    <!-- 流程配置对话框 -->
    <el-dialog v-model="workflowConfigVisible" title="流程配置" width="500px">
      <el-form :model="workflowConfig" label-width="100px">
        <el-form-item label="流程名称">
          <el-input v-model="workflowConfig.name" placeholder="请输入流程名称" />
        </el-form-item>
        <el-form-item label="流程描述">
          <el-input v-model="workflowConfig.description" type="textarea" placeholder="请输入流程描述" />
        </el-form-item>
        <el-form-item label="流程分类">
          <el-select v-model="workflowConfig.category">
            <el-option label="审批流程" value="approval" />
            <el-option label="业务流程" value="business" />
            <el-option label="系统流程" value="system" />
          </el-select>
        </el-form-item>
        <el-form-item label="启用状态">
          <el-switch v-model="workflowConfig.enabled" />
        </el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="workflowConfigVisible = false">取消</el-button>
        <el-button type="primary" @click="saveWorkflowConfig">确定</el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, computed, nextTick, onMounted, onUnmounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import {
  DocumentAdd, CircleCheck, Delete, ZoomIn, ZoomOut, FullScreen, Setting,
  Close, User, Document, ScaleToOriginal, Connection, Bell, Code,
  ArrowRight, QuestionFilled, Flag, Timer
} from '@element-plus/icons-vue'

// 节点类型配置
const nodeGroups = ref([
  {
    name: '基础节点',
    nodes: [
      { type: 'start', label: '开始', icon: 'Flag', color: 'success' },
      { type: 'end', label: '结束', icon: 'CircleCheck', color: 'danger' },
      { type: 'task', label: '任务', icon: 'Document', color: 'primary' }
    ]
  },
  {
    name: '流程控制',
    nodes: [
      { type: 'condition', label: '条件判断', icon: 'QuestionFilled', color: 'warning' },
      { type: 'parallel', label: '并行网关', icon: 'Connection', color: 'info' },
      { type: 'timer', label: '定时器', icon: 'Timer', color: 'success' }
    ]
  },
  {
    name: '人工节点',
    nodes: [
      { type: 'approval', label: '审批', icon: 'User', color: 'primary' },
      { type: 'manual', label: '人工任务', icon: 'Edit', color: 'warning' }
    ]
  },
  {
    name: '系统节点',
    nodes: [
      { type: 'script', label: '脚本任务', icon: 'Code', color: 'info' },
      { type: 'notification', label: '通知', icon: 'Bell', color: 'success' },
      { type: 'service', label: '服务调用', icon: 'Link', color: 'primary' }
    ]
  }
])

// 流程配置
const workflowConfig = reactive({
  name: '',
  description: '',
  category: 'approval',
  enabled: true
})

// 画布状态
const zoomLevel = ref(1)
const panX = ref(0)
const panY = ref(0)
const canvasContainer = ref(null)

// 节点和连接
const workflowNodes = ref([])
const connections = ref([])
const selectedNode = ref(null)
const selectedConnection = ref(null)

// 拖拽状态
const isDragging = ref(false)
const dragNode = ref(null)
const dragOffset = ref({ x: 0, y: 0 })

// 连接状态
const isConnecting = ref(false)
const connectionStart = ref(null)
const tempConnection = ref(null)
const mousePosition = ref({ x: 0, y: 0 })

// 对话框状态
const workflowConfigVisible = ref(false)

// 获取节点配置
const getNodeConfig = (type) => {
  for (const group of nodeGroups.value) {
    const node = group.nodes.find(n => n.type === type)
    if (node) return node
  }
  return { label: '未知节点', icon: 'QuestionFilled', color: 'info' }
}

// 节点拖拽开始
const handleNodeDragStart = (node) => {
  window.dragNodeType = node
}

// 画布拖拽处理
const handleCanvasDragOver = (e) => {
  e.preventDefault()
}

// 画布放置处理
const handleCanvasDrop = (e) => {
  e.preventDefault()
  const nodeType = window.dragNodeType
  if (nodeType) {
    const rect = canvasContainer.value.getBoundingClientRect()
    const x = (e.clientX - rect.left) / zoomLevel.value - panX.value
    const y = (e.clientY - rect.top) / zoomLevel.value - panY.value
    addNode(nodeType, x, y)
  }
}

// 添加节点
const addNode = (nodeType, x, y) => {
  const id = Date.now().toString()
  const node = {
    id,
    type: nodeType.type,
    title: nodeType.label,
    description: '',
    x: x - 75, // 节点宽度的一半
    y: y - 40, // 节点高度的一半
    config: getDefaultNodeConfig(nodeType.type)
  }
  
  workflowNodes.value.push(node)
  selectedNode.value = node
}

// 获取默认节点配置
const getDefaultNodeConfig = (type) => {
  const configs = {
    approval: {
      approver: 'direct_manager',
      approvalType: 'single',
      timeout: 24
    },
    condition: {
      conditions: []
    },
    script: {
      scriptType: 'javascript',
      script: ''
    },
    notification: {
      notifyMethods: ['system'],
      recipients: '',
      template: ''
    }
  }
  return configs[type] || {}
}

// 选择节点
const selectNode = (node) => {
  selectedNode.value = node
  selectedConnection.value = null
}

// 选择连接
const selectConnection = (connection) => {
  selectedConnection.value = connection
  selectedNode.value = null
}

// 画布点击
const handleCanvasClick = (e) => {
  if (e.target === e.currentTarget || e.target.classList.contains('canvas')) {
    selectedNode.value = null
    selectedConnection.value = null
  }
}

// 开始拖拽节点
const startDrag = (node, e) => {
  if (e.button !== 0) return // 只处理左键
  
  isDragging.value = true
  dragNode.value = node
  
  const rect = canvasContainer.value.getBoundingClientRect()
  dragOffset.value = {
    x: (e.clientX - rect.left) / zoomLevel.value - panX.value - node.x,
    y: (e.clientY - rect.top) / zoomLevel.value - panY.value - node.y
  }
  
  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
}

// 鼠标移动
const handleMouseMove = (e) => {
  if (isDragging.value && dragNode.value) {
    const rect = canvasContainer.value.getBoundingClientRect()
    dragNode.value.x = (e.clientX - rect.left) / zoomLevel.value - panX.value - dragOffset.value.x
    dragNode.value.y = (e.clientY - rect.top) / zoomLevel.value - panY.value - dragOffset.value.y
  }
  
  if (isConnecting.value) {
    const rect = canvasContainer.value.getBoundingClientRect()
    mousePosition.value = {
      x: (e.clientX - rect.left) / zoomLevel.value - panX.value,
      y: (e.clientY - rect.top) / zoomLevel.value - panY.value
    }
  }
}

// 鼠标释放
const handleMouseUp = () => {
  isDragging.value = false
  dragNode.value = null
  isConnecting.value = false
  connectionStart.value = null
  tempConnection.value = null
  
  document.removeEventListener('mousemove', handleMouseMove)
  document.removeEventListener('mouseup', handleMouseUp)
}

// 处理连接点
const handleConnectionPoint = (node, type) => {
  if (type === 'output') {
    // 开始连接
    isConnecting.value = true
    connectionStart.value = { node, type }
    tempConnection.value = {
      start: { x: node.x + 75, y: node.y + 40 },
      end: { x: node.x + 75, y: node.y + 40 }
    }
  } else if (type === 'input' && isConnecting.value && connectionStart.value) {
    // 完成连接
    createConnection(connectionStart.value.node, node)
    isConnecting.value = false
    connectionStart.value = null
    tempConnection.value = null
  }
}

// 创建连接
const createConnection = (fromNode, toNode) => {
  const id = Date.now().toString()
  const connection = {
    id,
    from: fromNode.id,
    to: toNode.id
  }
  connections.value.push(connection)
}

// 获取连接路径
const getConnectionPath = (connection) => {
  const fromNode = workflowNodes.value.find(n => n.id === connection.from)
  const toNode = workflowNodes.value.find(n => n.id === connection.to)
  
  if (!fromNode || !toNode) return ''
  
  const startX = fromNode.x + 75
  const startY = fromNode.y + 80
  const endX = toNode.x + 75
  const endY = toNode.y
  
  const midY = (startY + endY) / 2
  
  return `M ${startX} ${startY} C ${startX} ${midY}, ${endX} ${midY}, ${endX} ${endY}`
}

// 获取临时连接路径
const getTempConnectionPath = () => {
  if (!tempConnection.value || !connectionStart.value) return ''
  
  const startX = connectionStart.value.node.x + 75
  const startY = connectionStart.value.node.y + 80
  const endX = mousePosition.value.x
  const endY = mousePosition.value.y
  
  const midY = (startY + endY) / 2
  
  return `M ${startX} ${startY} C ${startX} ${midY}, ${endX} ${midY}, ${endX} ${endY}`
}

// 移除节点
const removeNode = (node) => {
  const index = workflowNodes.value.findIndex(n => n.id === node.id)
  if (index > -1) {
    workflowNodes.value.splice(index, 1)
    // 移除相关连接
    connections.value = connections.value.filter(c => c.from !== node.id && c.to !== node.id)
    if (selectedNode.value?.id === node.id) {
      selectedNode.value = null
    }
  }
}

// 添加条件
const addCondition = () => {
  if (selectedNode.value && selectedNode.value.type === 'condition') {
    if (!selectedNode.value.config.conditions) {
      selectedNode.value.config.conditions = []
    }
    selectedNode.value.config.conditions.push({
      field: '',
      operator: 'eq',
      value: ''
    })
  }
}

// 移除条件
const removeCondition = (index) => {
  if (selectedNode.value && selectedNode.value.config.conditions) {
    selectedNode.value.config.conditions.splice(index, 1)
  }
}

// 缩放控制
const handleZoomIn = () => {
  zoomLevel.value = Math.min(zoomLevel.value * 1.2, 3)
}

const handleZoomOut = () => {
  zoomLevel.value = Math.max(zoomLevel.value / 1.2, 0.3)
}

const handleFitView = () => {
  zoomLevel.value = 1
  panX.value = 0
  panY.value = 0
}

// 流程配置
const handleWorkflowConfig = () => {
  workflowConfigVisible.value = true
}

const saveWorkflowConfig = () => {
  workflowConfigVisible.value = false
  ElMessage.success('流程配置已保存')
}

// 验证流程
const handleValidate = () => {
  const errors = []
  
  // 检查是否有开始节点
  const startNodes = workflowNodes.value.filter(n => n.type === 'start')
  if (startNodes.length === 0) {
    errors.push('流程必须包含一个开始节点')
  } else if (startNodes.length > 1) {
    errors.push('流程只能包含一个开始节点')
  }
  
  // 检查是否有结束节点
  const endNodes = workflowNodes.value.filter(n => n.type === 'end')
  if (endNodes.length === 0) {
    errors.push('流程必须包含至少一个结束节点')
  }
  
  // 检查节点连接
  for (const node of workflowNodes.value) {
    if (node.type !== 'start') {
      const hasInput = connections.value.some(c => c.to === node.id)
      if (!hasInput) {
        errors.push(`节点 "${node.title}" 没有输入连接`)
      }
    }
    
    if (node.type !== 'end') {
      const hasOutput = connections.value.some(c => c.from === node.id)
      if (!hasOutput) {
        errors.push(`节点 "${node.title}" 没有输出连接`)
      }
    }
  }
  
  if (errors.length > 0) {
    ElMessage.error(`流程验证失败：\n${errors.join('\n')}`)
  } else {
    ElMessage.success('流程验证通过')
  }
}

// 清空画布
const handleClear = () => {
  ElMessageBox.confirm('确定要清空画布吗？', '提示', {
    confirmButtonText: '确定',
    cancelButtonText: '取消',
    type: 'warning'
  }).then(() => {
    workflowNodes.value = []
    connections.value = []
    selectedNode.value = null
    selectedConnection.value = null
    ElMessage.success('画布已清空')
  })
}

// 保存流程
const handleSave = () => {
  if (!workflowConfig.name) {
    ElMessage.warning('请先配置流程名称')
    return
  }
  
  if (workflowNodes.value.length === 0) {
    ElMessage.warning('请先添加流程节点')
    return
  }
  
  const workflowData = {
    config: workflowConfig,
    nodes: workflowNodes.value,
    connections: connections.value
  }
  
  console.log('保存流程:', workflowData)
  ElMessage.success('流程保存成功！')
}

// 组件挂载
onMounted(() => {
  document.addEventListener('mousemove', handleMouseMove)
  document.addEventListener('mouseup', handleMouseUp)
})

// 组件卸载
onUnmounted(() => {
  document.removeEventListener('mousemove', handleMouseMove)
  document.removeEventListener('mouseup', handleMouseUp)
})
</script>

<style scoped>
.workflow-designer {
  height: 100vh;
  display: flex;
  flex-direction: column;
  background: #f5f7fa;
}

.toolbar {
  height: 60px;
  background: white;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
}

.toolbar-left {
  display: flex;
  gap: 10px;
}

.toolbar-right {
  display: flex;
  align-items: center;
  gap: 16px;
}

.workflow-name {
  font-size: 16px;
  font-weight: 500;
  color: #303133;
}

.designer-container {
  flex: 1;
  display: flex;
  overflow: hidden;
}

.node-panel {
  width: 280px;
  background: white;
  border-right: 1px solid #e4e7ed;
  overflow-y: auto;
}

.canvas-panel {
  flex: 1;
  background: white;
  margin: 0 1px;
  overflow: hidden;
}

.property-panel {
  width: 320px;
  background: white;
  border-left: 1px solid #e4e7ed;
  overflow-y: auto;
}

.panel-header {
  height: 50px;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 0 20px;
}

.panel-header h3 {
  margin: 0;
  font-size: 14px;
  font-weight: 500;
  color: #303133;
}

.zoom-info {
  font-size: 12px;
  color: #909399;
}

.node-list {
  padding: 20px;
}

.node-group {
  margin-bottom: 20px;
}

.group-title {
  font-size: 12px;
  color: #909399;
  margin-bottom: 10px;
  font-weight: 500;
}

.group-items {
  display: flex;
  flex-direction: column;
  gap: 8px;
}

.node-item {
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  cursor: grab;
  display: flex;
  align-items: center;
  gap: 12px;
  transition: all 0.3s;
  background: white;
}

.node-item:hover {
  border-color: #409eff;
  box-shadow: 0 2px 8px rgba(64, 158, 255, 0.2);
}

.node-item:active {
  cursor: grabbing;
}

.node-icon {
  width: 32px;
  height: 32px;
  border-radius: 6px;
  display: flex;
  align-items: center;
  justify-content: center;
  color: white;
}

.node-icon.primary { background: #409eff; }
.node-icon.success { background: #67c23a; }
.node-icon.warning { background: #e6a23c; }
.node-icon.danger { background: #f56c6c; }
.node-icon.info { background: #909399; }

.node-item span {
  font-size: 14px;
  color: #303133;
}

.canvas-container {
  flex: 1;
  position: relative;
  overflow: hidden;
  cursor: grab;
}

.canvas {
  width: 100%;
  height: 100%;
  position: relative;
  transform-origin: 0 0;
}

.grid-background {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-image: 
    radial-gradient(circle, #e4e7ed 1px, transparent 1px);
  background-size: 20px 20px;
  pointer-events: none;
}

.connections {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 1;
}

.connection-line {
  pointer-events: stroke;
  cursor: pointer;
}

.temp-connection {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  pointer-events: none;
  z-index: 2;
}

.workflow-node {
  position: absolute;
  width: 150px;
  min-height: 80px;
  background: white;
  border: 2px solid #e4e7ed;
  border-radius: 8px;
  cursor: move;
  z-index: 10;
  transition: all 0.3s;
}

.workflow-node:hover {
  border-color: #409eff;
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.2);
}

.workflow-node.active {
  border-color: #409eff;
  box-shadow: 0 4px 12px rgba(64, 158, 255, 0.3);
}

.workflow-node.start {
  border-color: #67c23a;
}

.workflow-node.end {
  border-color: #f56c6c;
}

.workflow-node.condition {
  border-color: #e6a23c;
}

.node-header {
  padding: 8px 12px;
  border-bottom: 1px solid #e4e7ed;
  display: flex;
  align-items: center;
  gap: 8px;
  background: #fafafa;
  border-radius: 6px 6px 0 0;
}

.node-header .node-icon {
  width: 20px;
  height: 20px;
  border-radius: 4px;
}

.node-title {
  flex: 1;
  font-size: 12px;
  font-weight: 500;
  color: #303133;
}

.node-delete {
  width: 20px;
  height: 20px;
  padding: 0;
  border: none;
}

.node-content {
  padding: 12px;
}

.node-description {
  font-size: 12px;
  color: #606266;
  line-height: 1.4;
}

.connection-point {
  position: absolute;
  width: 12px;
  height: 12px;
  border: 2px solid #409eff;
  border-radius: 50%;
  background: white;
  cursor: crosshair;
  z-index: 20;
}

.connection-point.input {
  top: -6px;
  left: 50%;
  transform: translateX(-50%);
}

.connection-point.output {
  bottom: -6px;
  left: 50%;
  transform: translateX(-50%);
}

.connection-point:hover {
  background: #409eff;
  transform: translateX(-50%) scale(1.2);
}

.property-content {
  padding: 20px;
}

.no-selection {
  text-align: center;
  color: #909399;
  padding: 40px 0;
}

.config-group {
  margin-bottom: 24px;
}

.config-group .group-title {
  font-size: 14px;
  color: #303133;
  margin-bottom: 16px;
  font-weight: 500;
  border-bottom: 1px solid #e4e7ed;
  padding-bottom: 8px;
}

.condition-list {
  display: flex;
  flex-direction: column;
  gap: 12px;
}

.condition-item {
  padding: 12px;
  border: 1px solid #e4e7ed;
  border-radius: 6px;
  background: #fafafa;
}
</style>